package com.zxy.ziems.server.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zxy.btp.common.exception.ConditionException;
import com.zxy.btp.common.response.PageResult;
import com.zxy.ziems.server.convert.OrgConvert;
import com.zxy.ziems.server.domain.Org;
import com.zxy.ziems.server.domain.User;
import com.zxy.ziems.server.dto.OrgDto;
import com.zxy.ziems.server.dto.OrgQueryDto;
import com.zxy.ziems.server.dto.OrgTreeNode;
import com.zxy.ziems.server.mapper.OrgMapper;
import com.zxy.ziems.server.mybatis.core.service.ServiceImplX;
import com.zxy.ziems.server.service.OrgDeptRelService;
import com.zxy.ziems.server.service.OrgService;
import com.zxy.ziems.server.service.UserService;
import com.zxy.ziems.server.utils.AssertUtil;
import com.zxy.ziems.server.utils.tree.TreeUtils;
import com.zxy.ziems.server.vo.OrgVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bhg
 * @date 2023/3/9
 */
@Service
@Slf4j
public class OrgServiceImpl extends ServiceImplX<OrgMapper, Org> implements OrgService {
    @Autowired
    private OrgMapper orgMapper;
    @Autowired
    private OrgDeptRelService orgDeptRelService;
    @Autowired
    private UserService userService;
    private static final String BASE_DEPT_ID = "-1";

    @Override
    @Transactional(readOnly = true)
    public PageResult<OrgVo> pageList(OrgQueryDto orgQueryDto) {
        

        //组装wrapper
        QueryWrapper<Org> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ObjectUtil.isNotEmpty(orgQueryDto.getParentDeptId()), Org::getParentOrgId, orgQueryDto.getParentDeptId());
        queryWrapper.lambda().like(ObjectUtil.isNotEmpty(orgQueryDto.getOrgCode()), Org::getOrgCode, orgQueryDto.getOrgCode());
        queryWrapper.lambda().eq(ObjectUtil.isNotEmpty(orgQueryDto.getOrgLevel()), Org::getOrgLevel, orgQueryDto.getOrgLevel());
        queryWrapper.lambda().like(ObjectUtil.isNotEmpty(orgQueryDto.getOrgName()), Org::getOrgName, orgQueryDto.getOrgName());
        queryWrapper.lambda().orderByDesc(Org::getUpdateTime);
        Page<Org> page = orgMapper.selectPage(new Page<>(orgQueryDto.getPageNo(), orgQueryDto.getPageSize()), queryWrapper);
        List<Org> records = page.getRecords();
        //空值
        if (ObjectUtil.isEmpty(records)) {
            return new PageResult<>(page.getTotal(), Collections.emptyList());
        }
        List<OrgVo> orgVoList = OrgConvert.INSTANCE.orgListToOrgVoList(records);
        //父级id
        List<String> parentIds = orgVoList.stream().map(OrgVo::getParentOrgId).collect(Collectors.toList());
        Map<String, String> map = null;
        if (ObjectUtil.isNotEmpty(parentIds)) {
            List<Org> parentOrgList = orgMapper.selectBatchIds(parentIds);
            map = parentOrgList.stream().collect(Collectors.toMap(Org::getOrgId, Org::getOrgName));

        }
        List<String> userIdList = orgVoList.stream().map(OrgVo::getBossId).toList();
        //负责人
        Map<String, String> userMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(userIdList)) {
            List<User> userList = userService.listByIds(userIdList);
            userMap = userList.stream().collect(Collectors.toMap(User::getUserId, User::getUserName));
        }
        for (OrgVo orgVo : orgVoList) {
            orgVo.setParentOrgName(map.get(orgVo.getParentOrgId()));
            orgVo.setBossName(userMap.get(orgVo.getBossId()));
        }
        return new PageResult<>(page.getTotal(), orgVoList);
    }

    /**
     * 获取名称对应父级id
     *
     * @param parentName
     * @return
     */
    private List<String> getParentOrgId(String parentName) {
        QueryWrapper<Org> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().like(Org::getOrgName, parentName);
        queryWrapper.lambda().select(Org::getOrgId);
        List<Org> orgs = orgMapper.selectList(queryWrapper);
        if (ObjectUtil.isNotEmpty(orgs)) {
            return orgs.stream().map(Org::getOrgId).toList();
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrUpdate(OrgDto orgDto) {
        String orgId = orgDto.getOrgId();
        checkCode(orgDto);
        //转化
        Org org = OrgConvert.INSTANCE.orgDtoToOrg(orgDto);
        if (StrUtil.isEmpty(orgId)) {
            orgMapper.insert(org);
        } else {
            orgMapper.updateById(org);
        }
    }

    /**
     * 校验编码
     *
     * @param orgDto
     */
    private void checkCode(OrgDto orgDto) {
        String orgCode = orgDto.getOrgCode();
        Org org = getOne(Org::getOrgCode, orgCode);
        AssertUtil.isFalse(Objects.nonNull(org) && !Objects.equals(org.getOrgId(), orgDto.getOrgId()), "编码重复，请重新填写！");
        if (StrUtil.isBlank(orgDto.getParentOrgId())) {
            orgDto.setParentOrgId("0");
        }
        if (!"0".equals(orgDto.getParentOrgId())) {
            AssertUtil.nonNull(getOne(Org::getOrgId, orgDto.getParentOrgId()), "编码重复，请重新填写！");
        }
    }

    @Override
    @Transactional(readOnly = true)
    public OrgVo detail(String orgId) {
        Org org = orgMapper.selectById(orgId);
        OrgVo orgVo = OrgConvert.INSTANCE.orgToOrgVo(org);
        //父级组织
        if (ObjectUtil.isNotEmpty(org.getParentOrgId()) && !"-1".equals(org.getParentOrgId())) {
            Org parentOrg = orgMapper.selectById(orgVo.getParentOrgId());
            orgVo.setParentOrgName(parentOrg.getOrgName());
        }
        //查询负责人信息
        if (ObjectUtil.isNotEmpty(org.getBossId())) {
            User bossUser = userService.getById(org.getBossId());
            orgVo.setBossName(bossUser.getUserName());
        }

        return orgVo;
    }

    @Override
    @Transactional(readOnly = true)
    public List<OrgTreeNode> tree() {
        //组建最高级-企业名称
        List<Org> orgList = orgMapper.selectList(null);
        //空值
        if (ObjectUtil.isEmpty(orgList)) {
            return new ArrayList<>(0);
        }

        List<OrgTreeNode> list = orgList.stream().map((org) -> {
            OrgTreeNode node = new OrgTreeNode(org.getOrgId(), org.getOrgName(), org.getOrgCode(), org.getParentOrgId());
            return node;
        }).collect(Collectors.toList());
        //获取树

        return TreeUtils.tree(list);
    }

    @Override
    public List<Org> listByIds(Collection<? extends Serializable> idList) {
        if (CollectionUtil.isEmpty(idList)) {
            return new ArrayList<>(0);
        }
        return super.listByIds(idList);
    }

    @Override
    public void deleteById(Serializable id) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        List<User> userList = userService.list(queryWrapper.lambda().eq(User::getOrgId, id));
        if (CollectionUtil.isNotEmpty(userList)) {
            throw new ConditionException("请先移除该组织下的用户");
        }
        removeById(id);
    }

    @Override
    public List<OrgVo> getChildren(String orgId) {
        if (StrUtil.isBlank(orgId)) {
            return new ArrayList<>(0);
        }
        Org org = getById(orgId);
        if (Objects.isNull(org)) {
            return new ArrayList<>(0);
        }
        List<Org> list = list(Org::getParentOrgId, orgId);
        Set<String> bossIdSet = list.stream().map(Org::getBossId).collect(Collectors.toSet());
        Map<String, User> userMap = userService.listByIds(bossIdSet).stream().collect(Collectors.toMap(User::getUserId, (a) -> a));

        return list.stream().map((a) -> {
            OrgVo orgVo = OrgConvert.INSTANCE.orgToOrgVo(a);
            //父级组织
            orgVo.setParentOrgName(org.getOrgName());

            //查询负责人信息
            if (ObjectUtil.isNotEmpty(a.getBossId())) {
                User bossUser = userMap.get(a.getBossId());
                orgVo.setBossName(bossUser.getUserName());
            }
            return orgVo;
        }).collect(Collectors.toList());
    }
}
